package com.wujunshen.utils;

import com.wujunshen.exception.MyException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;

/**
 * @author wujunshen
 * @version 1.0
 * @since 1.0
 */
public interface RequestSender<T> {
    /**
     * 检查请求参数
     * @return 请求参数是否合法
     */
    default boolean checkParams() {
        return true;
    }

    /**
     * 读取结果
     * @param statusCode HTTP状态码
     * @param httpHeads  HTTP头
     * @param httpEntity HTTP实体
     * @return 泛型
     */
    T readResult(int statusCode, Map<String, String> httpHeads, HttpEntity httpEntity);

    /**
     * 发送
     * @return 泛型对象
     */
    default T send() {
        if (!checkParams()) {
            throw new MyException("params missing or wrong -> params[" + getParams() + "].");
        }

        Address address = getAddress();
        String url = address.getDomain() + address.getMapping();

        CloseableHttpResponse response = NetUtils.sendHttpRequest(url, getParams(), getHeaders(), address.getMethod());

        return (response == null)
                ? null
                : readResult(response.getStatusLine().getStatusCode(), getAllHeaders(response), response.getEntity());
    }

    /**
     * 获取Address
     * @return Address
     */
    Address getAddress();

    /**
     * 获取所有Http头信息
     * @param response 响应对象
     * @return 所有Http头信息
     */
    private Map<String, String> getAllHeaders(final CloseableHttpResponse response) {
        Map<String, String> result = new HashMap<>(response.getAllHeaders().length);

        Arrays.stream(response.getAllHeaders()).forEach(element -> result.put(element.getName(), element.getValue()));

        return result;
    }

    /**
     * http头信息
     * @return http头信息
     */
    default Map<String, String> getHeaders() {
        return Collections.emptyMap();
    }

    /**
     * 请求参数
     * @return 请求参数
     */
    default Map<String, String> getParams() {
        return Collections.emptyMap();
    }
}
